package rmdb

import (
	"errors"
	"fmt"

	s "gitee.com/xiaoa7/jsetl/service"
	jsvmcore "gitee.com/xiaoa7/jsvm-core"
	"github.com/dop251/goja"
)

// 获取数据库实例
func getInstance(id string) (*RMDB, error) {
	if ins := s.GetService(id); ins != nil {
		if _redis, ok := ins.(*RMDB); ok {
			return _redis, nil
		} else {
			return nil, errors.New("rmdb instance type error")
		}
	}
	return nil, errors.New("can't find rmdb instance")
}

// 执行sql查询
func (r *RMDB) query(sql string, params ...interface{}) (result []map[string]interface{}, err error) {
	//log.Println(sql, params)
	rows, err := r.database.Query(sql, params...)
	if err != nil {
		return
	}
	defer rows.Close()
	// 获取列信息
	columns, err := rows.Columns()
	if err != nil {
		return nil, fmt.Errorf("获取列信息失败: %v", err)
	}
	// 准备存储结果的切片
	result = make([]map[string]interface{}, 0)
	// 为每一行数据创建一个接口切片，用于 Scan
	values := make([]interface{}, len(columns))
	valuePtrs := make([]interface{}, len(columns))
	// 遍历每一行
	for rows.Next() {
		// 为每个字段创建指针
		for i := range values {
			valuePtrs[i] = &values[i]
		}
		// 扫描行数据到指针切片中
		if err := rows.Scan(valuePtrs...); err != nil {
			return nil, fmt.Errorf("扫描行数据失败: %v", err)
		}
		// 创建当前行的 map
		row := make(map[string]interface{})
		for i, col := range columns {
			// 处理 NULL 值
			val := values[i]
			if val == nil {
				row[col] = nil
				continue
			}
			// 检查是否是 sql.RawBytes 类型，需要转换为字符串
			if b, ok := val.([]byte); ok {
				row[col] = string(b)
			} else {
				row[col] = val
			}
		}
		// 将当前行添加到结果切片
		result = append(result, row)
	}
	// 检查遍历过程中是否有错误
	if err = rows.Err(); err != nil {
		return nil, fmt.Errorf("行遍历错误: %v", err)
	}
	return
}

// 执行sql
func (r *RMDB) execute(sql string, params ...interface{}) error {
	_, err := r.database.Exec(sql, params...)
	return err
}

// 注册数据库操作
func init() {
	//rmdb操作jsvm绑定
	jsvmcore.RegisterObject("rmdb", map[string]jsvmcore.HandleFn{
		"connect": func(vm *jsvmcore.JsVM) jsvmcore.JsVmFn {
			return func(params ...interface{}) goja.Value {
				if len(params) < 2 {
					return vm.State.ToValue("无效的输入参数")
				}
				rmdbInstance, _ := params[0].(string)
				//fmt.Println("ins", rmdbInstance)
				_params := make([]string, len(params)-1)
				for i := 0; i < len(_params); i++ {
					_params[i], _ = params[i+1].(string)
				}
				if err := ConnectDB(rmdbInstance, _params...); err == nil {
					return vm.State.ToValue("connect sucess")
				} else {
					return vm.State.ToValue(err.Error())
				}
			}
		},
		"query": func(vm *jsvmcore.JsVM) jsvmcore.JsVmFn {
			return func(params ...interface{}) goja.Value {
				if len(params) < 2 {
					return vm.State.ToValue("无效的输入参数")
				}
				rmdbInstance, _ := params[0].(string)
				//fmt.Println("ins", rmdbInstance)
				sqlStr, _ := params[1].(string)
				if _db, err := getInstance(rmdbInstance); err == nil {
					if rs, err := _db.query(sqlStr, params[2:]...); err != nil {
						return vm.State.ToValue(err.Error())
					} else {
						return vm.State.ToValue(rs)
					}
				} else {
					return vm.State.ToValue(err.Error())
				}
			}
		},
		"execute": func(vm *jsvmcore.JsVM) jsvmcore.JsVmFn {
			return func(params ...interface{}) goja.Value {
				if len(params) < 2 {
					return vm.State.ToValue("无效的输入参数")
				}
				rmdbInstance, _ := params[0].(string)
				sqlStr, _ := params[1].(string)
				if _db, err := getInstance(rmdbInstance); err == nil {
					if err := _db.execute(sqlStr, params[2:]...); err != nil {
						return vm.State.ToValue(err.Error())
					} else {
						return vm.State.ToValue("")
					}
				}
				return vm.State.ToValue("")
			}
		},
	})
}
